<template>
  <div class="modal-form">
    <el-dialog v-model="modalVisible" :title="props.title" :close-on-click-modal="false" @closed="onClosed">
      <template #default>
        <el-scrollbar>
          <div class="operate-form">
            <el-form ref="formRef" :model="form" :rules="props.modalConfig.formRules" label-width="160px">
              <template v-for="formItem in props.modalConfig.formItems" :key="formItem.prop">
                <el-form-item :label="formItem.label" :prop="formItem.prop">
                  <template v-if="formItem.type === 'text'">
                    <el-input v-model="form[formItem.prop]" :placeholder="formItem.placeholder" />
                  </template>

                  <template v-else-if="formItem.type === 'password'">
                    <el-input v-model="form[formItem.prop]" type="password" :placeholder="formItem.placeholder" />
                  </template>

                  <template v-else-if="formItem.type === 'select'">
                    <el-select v-model="form[formItem.prop]" :placeholder="formItem.placeholder">
                      <el-option
                        v-for="(option, index) in formItem.options"
                        :key="index"
                        :label="option.label"
                        :value="option.value"
                      />
                    </el-select>
                  </template>

                  <template v-else-if="formItem.type === 'switch'">
                    <el-switch v-model="form[formItem.prop]" />
                  </template>

                  <template v-else-if="formItem.type === 'checkbox-group'">
                    <el-checkbox-group v-model="form[formItem.prop]">
                      <el-checkbox
                        v-for="(option, index) in formItem.options"
                        :key="index"
                        :value="option.value"
                        :name="formItem.prop"
                      >
                        {{ option.label }}
                      </el-checkbox>
                    </el-checkbox-group>
                  </template>

                  <template v-else-if="formItem.type === 'radio-group'">
                    <el-radio-group v-model="form[formItem.prop]">
                      <el-radio v-for="(option, index) in formItem.options" :key="index" :value="option.value">
                        {{ option.label }}
                      </el-radio>
                    </el-radio-group>
                  </template>

                  <template v-else-if="formItem.type === 'textarea'">
                    <el-input v-model="form[formItem.prop]" type="textarea" />
                  </template>

                  <template v-else-if="formItem.type === 'custom'">
                    <slot :name="formItem.slotName || formItem.prop" />
                  </template>
                </el-form-item>
              </template>
            </el-form>
          </div>
        </el-scrollbar>
      </template>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeModal">取消</el-button>
          <el-button type="primary" color="var(--color-primary)" @click="handleConfirm">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from "vue"
import type { FormInstance } from "element-plus"
import type { ModalFormConfig } from "@/types/modal-form"

interface Props {
  title: string
  modalConfig: ModalFormConfig
  formData: Record<string, any>
}

const props = defineProps<Props>()

const emit = defineEmits<{
  submit: [formData: any]
}>()

const formRef = ref<FormInstance>()

/**
 * 初始化表单数据
 */
const form = ref({ ...props.formData })

// 当外部表单数据变化时，重新赋值
watch(
  () => props.formData,
  (newVal) => {
    form.value = newVal
  },
  { deep: true }
)

/**
 * 提交表单
 */
const handleConfirm = async () => {
  if (!formRef.value) return

  await formRef.value.validate((valid) => {
    if (valid) {
      emit("submit", { ...form.value })
    }
  })
}

const modalVisible = ref(false)

/**
 * 打开弹窗
 */
const openModal = () => {
  modalVisible.value = true
}

/**
 * 关闭弹窗
 */
const closeModal = () => {
  modalVisible.value = false
}

const onClosed = () => {
  // 清空数据和校验
  formRef.value?.resetFields()
  formRef.value?.clearValidate()
}

defineExpose({
  openModal,
  closeModal
})
</script>

<style lang="scss" scoped>
:deep(.el-dialog) {
  padding: 16px;

  .el-dialog__header {
    font-size: 18px;
    color: var(--color-black);
    border-bottom: 1px solid #f5f5f5;
  }

  .el-dialog__body {
    height: 58vh;
    padding-bottom: 52px;

    .operate-form {
      width: calc(100% - 80px);
      padding-top: 20px;
    }
  }

  .el-dialog__footer {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    padding: 10px 16px;
  }
}
</style>
